/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.ignite.examples.datagrid;

import java.util.HashMap;
import java.util.Map;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.IgniteException;
import org.apache.ignite.Ignition;
import org.apache.ignite.examples.ExampleNodeStartup;

/**
 * 缓存基础操作示例：演示缓存的基本put和get操作。
 *
 * 这是学习Ignite缓存功能的入门示例，展示了最基本的缓存操作：
 * - 创建或获取缓存
 * - 单个键值对的存储和读取
 * - 批量键值对的存储和读取
 *
 * 运行要求：
 * 1. 远程节点必须使用启用P2P类加载的特殊配置文件启动：
 *    {@code 'ignite.{sh|bat} examples/config/example-ignite.xml'}
 * 2. 或者在另一个JVM中运行 {@link ExampleNodeStartup} 类，
 *    它会使用相同的配置文件启动节点
 *
 * 学习要点：
 * - IgniteCache的基本用法
 * - try-with-resources确保资源正确释放
 * - put()和get()方法的基本使用
 * - putAll()和getAll()批量操作的优势
 *
 * 适用场景：
 * - Ignite入门学习
 * - 理解缓存基本概念
 * - 开发环境测试
 */
public class CachePutGetExample {
    /** 缓存名称：使用类名作为缓存名，确保命名唯一性 */
    private static final String CACHE_NAME = CachePutGetExample.class.getSimpleName();

    /**
     * 执行缓存示例的主方法。
     *
     * 这个方法会：
     * 1. 启动Ignite节点并加载配置文件
     * 2. 创建或获取指定名称的缓存
     * 3. 演示单个put/get操作
     * 4. 演示批量putAll/getAll操作
     * 5. 自动关闭资源，确保集群节点正常停止
     *
     * @param args 命令行参数，当前不需要任何参数
     * @throws IgniteException 如果示例执行失败
     */
    public static void main(String[] args) throws IgniteException {
        try (Ignite ignite = Ignition.start("examples/config/example-ignite.xml")) {
            try (IgniteCache<Integer, String> cache = ignite.getOrCreateCache(CACHE_NAME)) {
                // Individual puts and gets.
                putGet(cache);

                // Bulk puts and gets.
                putAllGetAll(cache);
            }
        }
    }

    /**
     * 执行单个键值对的put和get操作。
     *
     * 这个方法演示最基本的缓存操作：
     * - 使用for循环存储20个键值对（键为整数，值为对应的字符串）
     * - 再次遍历并读取所有值，验证数据是否正确存储
     * - 展示put()和get()方法的基本用法
     *
     * 数据格式：
     * - 键：0到19的整数
     * - 值：对应的字符串表示（"0", "1", "2", ..., "19"）
     *
     * @throws IgniteException 如果缓存操作失败
     */
    private static void putGet(IgniteCache<Integer, String> cache) throws IgniteException {
        System.out.println();
        System.out.println(">>> Cache put-get example started.");

        final int keyCnt = 20;

        // Store keys in cache.
        for (int i = 0; i < keyCnt; i++)
            cache.put(i, Integer.toString(i));

        System.out.println(">>> Stored values in cache.");

        for (int i = 0; i < keyCnt; i++)
            System.out.println("Got [key=" + i + ", val=" + cache.get(i) + ']');
    }

    /**
     * 执行批量putAll和getAll操作。
     *
     * 这个方法演示高效的批量操作：
     * - 创建一个Map包含20个键值对
     * - 使用putAll()一次性存储所有数据（比单独put更高效）
     * - 使用getAll()一次性读取所有数据（比单独get更高效）
     * - 展示批量操作在性能和代码简洁性上的优势
     *
     * 批量操作的优势：
     * - 减少网络往返次数
     * - 提高吞吐量
     * - 原子性保证
     * - 代码更简洁
     *
     * 数据格式：
     * - 键：0到19的整数
     * - 值：带有"bulk-"前缀的字符串（"bulk-0", "bulk-1", ..., "bulk-19"）
     *
     * @throws IgniteException 如果批量操作失败
     */
    private static void putAllGetAll(IgniteCache<Integer, String> cache) throws IgniteException {
        System.out.println();
        System.out.println(">>> Starting putAll-getAll example.");

        final int keyCnt = 20;

        // Create batch.
        Map<Integer, String> batch = new HashMap<>();

        for (int i = 0; i < keyCnt; i++)
            batch.put(i, "bulk-" + Integer.toString(i));

        // Bulk-store entries in cache.
        cache.putAll(batch);

        System.out.println(">>> Bulk-stored values in cache.");

        // Bulk-get values from cache.
        Map<Integer, String> vals = cache.getAll(batch.keySet());

        for (Map.Entry<Integer, String> e : vals.entrySet())
            System.out.println("Got entry [key=" + e.getKey() + ", val=" + e.getValue() + ']');
    }
}
